

#ifndef  BTREEPLUSNODEVIEW_H
#define  BTREEPLUSNODEVIEW_H

#include "common.h"
#include "BtreePlusStructs.h"

class Page;

class BtreePlusLeafNodeView;
class BtreePlusInteriorNodeView;
class IBtreePlusNodeView {
public:
    enum Type {
        Leaf,
        Interior,
    };
    IBtreePlusNodeView(Page * page, uint32_t degree);
    virtual ~IBtreePlusNodeView();

    virtual bool isLeaf() const  = 0;
    virtual bool isInterior() const = 0;

    Page * getPage() const { return page;}

    PageNumberType getPageNo() const ;

    IBtreePlusNodeView::Type getType() const;
    void setType(const IBtreePlusNodeView::Type type);

    PageNumberType getParent() const;
    void setParent(const PageNumberType parent);

    int getUsed() const;
    uint16_t & usedRef();

    bool isFull() { return getUsed() == getTotal();}

    int getTotal() const  { return full; }
    int getDegree() const  { return degree;}

    void reset(IBtreePlusNodeView::Type type);

    virtual RowIDType getKey(const int index) const = 0;
    virtual int setKey(const int index, const RowIDType key) = 0;

    virtual std::string toString() const = 0;

    static BtreePlusLeafNodeView * CreateLeaf(Page * page);
    static BtreePlusInteriorNodeView * CreateInterior(Page * page);
    static IBtreePlusNodeView * Load(Page * page);
    static BtreePlusLeafNodeView * LoadLeaf(Page * page);
    static BtreePlusInteriorNodeView * LoadInterior(Page * page);
    
    BtreePlusNode * getNode() const;

protected:
    Page * page; 
private:
    uint32_t degree;
    uint32_t full;
};

template<typename T>
class _Iterator {
public:
    virtual ~_Iterator(){}
    virtual bool hasNext() = 0;
    virtual T next() = 0;
};

class BtreePlusLeafNodeView: public IBtreePlusNodeView {
public:
    /* 
    class Iterator : public _Iterator<std::pair<RowIDType, const std::string&> >{
    public:
        Iterator(BtreePlusLeafNodeView * nv);
        virtual ~Iterator();
        bool hasNext() override;
        std::pair<RowIDType, const std::string &> next() override;
    private:
        uint32_t current;
    }*/

    BtreePlusLeafNodeView(Page * page);
    virtual ~BtreePlusLeafNodeView();

    bool isLeaf() const override { return true; }
    bool isInterior() const override { return false; }

    RowIDType getKey(const int index) const override;
    int setKey(const int index, const RowIDType key) override;

    std::string getValue(const int index) const ; //leaf Only
    int setValue(const int index, const std::string & data); //leaf only

    PageNumberType getNext() const; // leaf only
    int setNext(const PageNumberType next) ; // leaf only

    int append(const RowIDType key, const std::string & data);
    int insert(const int index, const RowIDType key, const std::string & data);
    int del(const int index);

    int insert(const RowIDType key, const std::string & data);

    std::string toString() const override;

    static void test();
private:
    void _setKeyNoCheck(const int index, const RowIDType key);
    void _setValueNoCheck(const int index, const std::string & data);
private:
    BtreePlusLeafNode * getLeafNode() const; 
};

class BtreePlusInteriorNodeView: public IBtreePlusNodeView {
public:
    BtreePlusInteriorNodeView(Page * page);
    virtual ~BtreePlusInteriorNodeView();

    PageNumberType getChild(const int index) const;
    int setChild(const int index, const PageNumberType child);

    bool isLeaf() const override { return false; }
    bool isInterior() const override { return true; }

    RowIDType getKey(const int index) const override;
    int setKey(const int index, const RowIDType key) override;

    int append(const RowIDType key, const PageNumberType child);
    int insert(const int index, const RowIDType key, const PageNumberType child);
    int del(const int index);

    std::string toString() const override;

    static void test();
private:
    void _setKeyNoCheck(const int index, const RowIDType key);
    void _setChildNoCheck(const int index, const PageNumberType child);

private:
    BtreePlusInteriorNode * getInteriorNode() const ;
};



#endif   /* BTREEPLUSNODEVIEW_H */
